﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;

using Microsoft.Practices.Unity;

using ERPStore.Extensions;
using ERPStore.NewsLetters.Models;
using ERPStore.NewsLetters.Extensions;

using EventBrokR;

namespace ERPStore.NewsLetters
{
	public class PluginInit : ERPStore.Extensibility.PluginInit
	{
		public PluginInit()
		{
			Container = ERPStore.GlobalConfiguration.Configuration.DependencyResolver.GetContainer();
		}

		protected Microsoft.Practices.Unity.IUnityContainer Container { get; private set; }

		public override void AddServices()
		{
			var settings = new ERPStore.NewsLetters.Models.Settings();
			settings.BindFromConfiguration(ERPStore.NewsLetters.Configuration.ConfigurationSettings.AppSettings);
			Container.RegisterInstance(settings, new ContainerControlledLifetimeManager());

			if (settings.RepositoryName == "mock")
			{
				Container.RegisterType<CloudSoft.Repositories.IRepository<Repositories.NewsLettersDbContext>, CloudSoft.Repositories.MemoryRepository<Repositories.NewsLettersDbContext>>(new ContainerControlledLifetimeManager());
			}
			else
			{
				Container.RegisterType<CloudSoft.Repositories.IRepository<Repositories.NewsLettersDbContext>, CloudSoft.Repositories.SqlRepository<Repositories.NewsLettersDbContext>>(new PerResolveLifetimeManager());
				Container.RegisterType<CloudSoft.Repositories.IDbContextFactory<Repositories.NewsLettersDbContext>, Repositories.DbContextFactory>(new PerResolveLifetimeManager());
				Container.RegisterType<CloudSoft.Repositories.IRepositoryInitializer, CloudSoft.Repositories.Initializers.SqlSchemaInitializer<Repositories.NewsLettersDbContext>>("newsletterssqlschemainitializer", new PerResolveLifetimeManager());
			}

			Container.RegisterType<Services.NewsLettersService>(new ContainerControlledLifetimeManager());
			Container.RegisterType<Services.TrackerService>(new ContainerControlledLifetimeManager());

			// Validators
			Container.RegisterType<global::FluentValidation.IValidator<Models.Campaign>, ModelValidators.CampaignValidator>("Validator:" + typeof(Models.Campaign).FullName, new ContainerControlledLifetimeManager());
			Container.RegisterType<global::FluentValidation.IValidator<Models.SMTPSettings>, ModelValidators.SMTPServerValidator>("Validator:" + typeof(Models.SMTPSettings).FullName, new ContainerControlledLifetimeManager());
			Container.RegisterType<global::FluentValidation.IValidator<Models.EmailListSource>, ModelValidators.EmailListSourceValidator>("Validator:" + typeof(Models.EmailListSource).FullName, new ContainerControlledLifetimeManager());
			Container.RegisterType<global::FluentValidation.IValidator<Models.NewsLetter>, ModelValidators.NewsLetterValidator>("Validator:" + typeof(Models.NewsLetter).FullName, new ContainerControlledLifetimeManager());
			Container.RegisterType<global::FluentValidation.IValidator<Models.PendingItem>, ModelValidators.PendingItemValidator>("Validator:" + typeof(Models.PendingItem).FullName, new ContainerControlledLifetimeManager());
			Container.RegisterType<global::FluentValidation.IValidator<Models.EmailRecipient>, ModelValidators.EmailRecipientValidator>("Validator:" + typeof(Models.EmailRecipient).FullName, new ContainerControlledLifetimeManager());

			// RecipientSourceProvider
			Container.RegisterType<Services.IEmailListSourceProvider, Services.DBContactRecipientSourceProvider>("DBContactRecipientSourceProvider", new ContainerControlledLifetimeManager());
			Container.RegisterType<Services.IEmailListSourceProvider, Services.AllContactRecipientSourceProvider>("AllContactRecipientSourceProvider", new ContainerControlledLifetimeManager());
			Container.RegisterType<Services.IEmailListSourceProvider, Services.ExternalRecipientSourceProvider>("ExternalRecipientSourceProvider", new ContainerControlledLifetimeManager());

			var eb = Container.Resolve<EventBrokR.IPublisher>();
			// EventConsumer
			eb.Container.Register<EventConsumers.ApplicationStartEventConsumer>();

			// Auto Mapping
			AutoMapper.Mapper.CreateMap<Repositories.Datas.SMTPServerData, Models.SMTPSettings>()
				.Bidirectional();

			AutoMapper.Mapper.CreateMap<Repositories.Datas.EmailListSourceData, Models.EmailListSource>()
				.ForMember(dest => dest.SourceTypeId, opt => opt.MapFrom(origin => origin.TypeId));
			AutoMapper.Mapper.CreateMap<Models.EmailListSource, Repositories.Datas.EmailListSourceData>()
				.ForMember(dest => dest.TypeId, opt => opt.MapFrom(origin => origin.SourceTypeId));

			// Newsletter
			AutoMapper.Mapper.CreateMap<Repositories.Datas.NewsLetterData, Models.NewsLetter>();
			AutoMapper.Mapper.CreateMap<Models.NewsLetter, Repositories.Datas.NewsLetterData>();

			// Campaign
			AutoMapper.Mapper.CreateMap<Repositories.Datas.CampaignData, Models.Campaign>()
				.ForMember(dest => dest.State, opt => opt.MapFrom(origin => (Models.SendState)Enum.Parse(typeof(Models.SendState), origin.StateId.ToString())))
				.ForMember(dest => dest.Stats, opt => opt.Ignore())
				.ForMember(dest => dest.EmailListSourceName, opt => opt.MapFrom(origin => origin.EmailListSource.Name))
				.ForMember(dest => dest.NewsLetterName, opt => opt.MapFrom(origin => origin.NewsLetter.FileName))
				.ForMember(dest => dest.SMTPServerName, opt => opt.MapFrom(origin => origin.SMTPServer.Name));
			AutoMapper.Mapper.CreateMap<Models.Campaign, Repositories.Datas.CampaignData>()
				.ForMember(dest => dest.StateId, opt => opt.MapFrom(origin => (int)origin.State));

			// EmailRecipient
			AutoMapper.Mapper.CreateMap<Repositories.Datas.EmailRecipientData, Models.EmailRecipient>()
				.ForMember(dest => dest.Presentation, opt => opt.MapFrom(origin => (ERPStore.Models.UserPresentation)Enum.Parse(typeof(ERPStore.Models.UserPresentation), origin.PresentationId.ToString())))
				.ForMember(dest => dest.IsBlackListed, opt => opt.MapFrom(origin => origin.UnsubscriptionId.HasValue));
			AutoMapper.Mapper.CreateMap<Models.EmailRecipient, Repositories.Datas.EmailRecipientData>()
				.ForMember(dest => dest.PresentationId, opt => opt.MapFrom(origin => (int)origin.Presentation));

			AutoMapper.Mapper.CreateMap<Repositories.Datas.EmailSentData, Models.EmailSentResult>()
				.ForMember(m => m.EmailRecipient, opt => opt.MapFrom(origin => origin.EmailRecipient));
			AutoMapper.Mapper.CreateMap<Models.EmailSentResult, Repositories.Datas.EmailSentData>()
				.ForMember(m => m.EmailRecipientId, opt => opt.MapFrom(origin => origin.EmailRecipient.Id));

			// PendingItem
			AutoMapper.Mapper.CreateMap<Repositories.Datas.PendingItemData, Models.PendingItem>()
				.Bidirectional();

			// TrackData
			AutoMapper.Mapper.CreateMap<Repositories.Datas.TrackData, Models.Track>()
				.Bidirectional();
			AutoMapper.Mapper.CreateMap<Repositories.Datas.UnsubscriptionData, Models.Unsubscription>()
				.Bidirectional();

			// EmailRecipient
			AutoMapper.Mapper.CreateMap<ERPStore.Models.User, ERPStore.NewsLetters.Models.EmailRecipient>()
				.ForMember(dest => dest.IsBlackListed, opt => opt.UseValue(false))
				.ForMember(dest => dest.Id, opt => opt.Ignore());

			// CampaignStat
			AutoMapper.Mapper.CreateMap<ERPStore.NewsLetters.Models.CampaignStat, Repositories.Datas.CampaignStatData>()
				.Bidirectional();

			// UserData
			AutoMapper.Mapper.CreateMap<Repositories.Datas.UserData, ERPStore.Models.User>()
				.ForMember(dest => dest.Corporate, opt => opt.MapFrom(source => source.CorporateName != null ? new ERPStore.Models.Corporate() { Name = source.CorporateName } : null));

			var logger = Container.Resolve<ERPStore.Logging.ILogger>();
			logger.Info("NewsLetters service layer configured");
		}

		public override void Load()
		{
			var serviceBus = Container.Resolve<ERPStore.Services.IServiceBus>();

			if (ERPStore.GlobalConfiguration.Configuration.HosterName == "SvcHost")
			{
				var medium = typeof(Ariane.MSMQMedium);
				if (ERPStore.GlobalConfiguration.Configuration.ExecutingContext == ERPStore.Models.ExecutingContext.Test)
				{
					medium = typeof(Ariane.InMemoryMedium);
				}

				serviceBus.RegisterQueue(Queues.QUEUE_TRACK, typeof(MessageReaders.NewsLetterTrackMessageReader), medium);
				serviceBus.RegisterQueue(Queues.QUEUE_SENT, typeof(MessageReaders.NewsLetterSentMessageReader), medium);
				serviceBus.RegisterQueue(Queues.QUEUE_SCHEDULE_CAMPAIGN, typeof(MessageReaders.ScheduleNewsLettersCampaignMessageReader), medium);
				serviceBus.RegisterQueue(Queues.QUEUE_SEND, typeof(MessageReaders.SendNewsLetterMessageReader), medium);
				if (GlobalConfiguration.Configuration.ExecutingContext != ERPStore.Models.ExecutingContext.Test)
				{
					serviceBus.RegisterQueue(Queues.QUEUE_BODY_CREATION, null, medium);
				}
			}

		}
	}
}
